package fun.tan90.wx.pay.rest;

import cn.hutool.json.JSONUtil;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.model.Transaction;
import fun.tan90.wx.pay.WxPayConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
@RequestMapping("/wx-pay/callback")
public class WxPayCallbackController {

    /**
     * 微信支付回调处理机制说明:
     * 商户系统不能仅依赖回调通知获取结果，需结合查询接口使用，避免遗漏或延迟问题。
     * 微信支付接收到商户的应答后，会根据应答结果做对应的逻辑处理：
     * 若商户应答回调接收成功，微信支付将不再重复发送该回调通知。若因网络或其他原因，商户收到了重复的回调通知，请做好重入设计并持续应答200
     * 若商户应答回调接收失败，或超时(5s)未应答时，微信支付会按照（15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h）的频次重复发送回调通知，直至微信支付接收到商户应答成功，或达到最大发送次数（15次）
     *
     * @param serial    验签的微信支付平台证书序列号/微信支付公钥ID
     * @param signature 验签的签名值
     * @param timestamp 验签的时间戳
     * @param nonce     验签的随机字符串
     * @param body      请求主体
     */
    @PostMapping("/order")
    public void orderCallback(
            @RequestHeader("Wechatpay-Serial") String serial,
            @RequestHeader("Wechatpay-Signature") String signature,
            @RequestHeader("Wechatpay-Timestamp") String timestamp,
            @RequestHeader("Wechatpay-Nonce") String nonce,
            @RequestBody String body) {
        log.info("serial: {}", serial);
        log.info("signature: {}", signature);
        log.info("timestamp: {}", timestamp);
        log.info("nonce: {}", nonce);
        log.info("body: {}", body);

        NotificationParser parser = new NotificationParser((NotificationConfig) WxPayConstant.CONFIG);

        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(serial)
                .nonce(nonce)
                .signature(signature)
                .timestamp(timestamp)
                .body(body)
                .build();

        //验签、解密并转换成 Transaction
        Transaction transaction = parser.parse(requestParam, Transaction.class);
        log.info("transaction：{}", JSONUtil.toJsonPrettyStr(transaction));
    }

    /**
     * 退款结果回调通知
     *
     * @param body
     */
    @PostMapping("/refunds")
    public void orderCallback(@RequestBody String body) {
        log.info("body: {}", body);
    }

}
